package com.fuhailiu.opengl.utils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;

import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.opengl.GLES30;

public class GlUtil {

	// RGBA
	public static final int BYTES_PER_PIXEL = 4;

	public static final int SIZE_OF_BYTE = 1;
	public static final int SIZE_OF_CHAR = 2;
	public static final int SIZE_OF_FLOAT = 4;
	public static final int SIZE_OF_DOUBLE = 8;

	public static final int SIZE_OF_SHORT = 2;
	public static final int SIZE_OF_INT = 4;
	public static final int SIZE_OF_LONG = 8;

	public static boolean supportOpenGLES30(Context context) {
		if (null == context) {
			return false;
		}
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		ConfigurationInfo info = am.getDeviceConfigurationInfo();
		return (info.reqGlEsVersion >= 0x30000);
	}

	// The extensions string is padded with spaces between extensions, but not
	// necessarily at the beginning or end. For simplicity, add spaces at the
	// beginning and end of the extensions string and the extension string.
	// This means we can avoid special-case checks for the first or last
	// extension, as well as avoid special-case checks when an extension name
	// is the same as the first part of another extension name.
	public static boolean supportExtension(String extension) {
		String ext = " " + GLES30.glGetString(GLES30.GL_EXTENSIONS) + " ";
		return ext.indexOf(" " + extension + " ") >= 0;
	}

	/**
	 * 检查每一步操作是否有错误
	 */
	public static void checkGlError(String operation) {
		int error = GLES30.glGetError();
		if (error != GLES30.GL_NO_ERROR) {
			String msg = operation + ": glError 0x" + Integer.toHexString(error);
			LogUtil.LogE("ES30_ERROR", msg);
			throw new RuntimeException(msg);
		}
	}

	public static ByteBuffer createByteBuffer(byte[] coords) {
		ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZE_OF_BYTE);
		bb.put(coords);
		bb.position(0);
		return bb;
	}

	public static CharBuffer createCharBuffer(char[] coords) {
		ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZE_OF_CHAR);
		bb.order(ByteOrder.nativeOrder());
		CharBuffer cb = bb.asCharBuffer();
		cb.put(coords);
		cb.position(0);
		return cb;
	}

	public static FloatBuffer createFloatBuffer(float[] coords) {
		ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZE_OF_FLOAT);
		bb.order(ByteOrder.nativeOrder());
		FloatBuffer fb = bb.asFloatBuffer();
		fb.put(coords);
		fb.position(0);
		return fb;
	}

	public static DoubleBuffer createDoubleBuffer(double[] coords) {
		ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZE_OF_DOUBLE);
		bb.order(ByteOrder.nativeOrder());
		DoubleBuffer db = bb.asDoubleBuffer();
		db.put(coords);
		db.position(0);
		return db;
	}

	public static ShortBuffer createShortBuffer(short[] coords) {
		ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZE_OF_SHORT);
		bb.order(ByteOrder.nativeOrder());
		ShortBuffer sb = bb.asShortBuffer();
		sb.put(coords);
		sb.position(0);
		return sb;
	}

	public static IntBuffer createIntBuffer(int[] coords) {
		ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZE_OF_INT);
		bb.order(ByteOrder.nativeOrder());
		IntBuffer ib = bb.asIntBuffer();
		ib.put(coords);
		ib.position(0);
		return ib;
	}

	public static LongBuffer createLongtBuffer(long[] coords) {
		ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZE_OF_LONG);
		bb.order(ByteOrder.nativeOrder());
		LongBuffer lb = bb.asLongBuffer();
		lb.put(coords);
		lb.position(0);
		return lb;
	}

}
